package com.hmdp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hmdp.dto.LoginFormDTO;
import com.hmdp.dto.Result;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.User;
import com.hmdp.mapper.UserMapper;
import com.hmdp.service.IUserService;
import com.hmdp.utils.RegexUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

import static com.hmdp.utils.RedisConstants.*;
import static com.hmdp.utils.SystemConstants.USER_NICK_NAME_PREFIX;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    //注入Redis
    @Autowired(required = false)
    private StringRedisTemplate stringRedisTemplate;
    //JSON工具
    private static  final ObjectMapper mapper=new ObjectMapper();

    @Override
    /**
     * 发送验证码
     */
    public Result sendCode(String phone) {
            //使用util下RegexUtils进行正则校验手机号
            if(RegexUtils.isPhoneInvalid(phone)) {
                //不符合则返回错误信息
                return Result.fail("手机号格式错误");
            }
            //生成验证码:导入hutool依赖，内有RandomUtil
            String code = RandomUtil.randomNumbers(6);
            log.info("code={}",code);

            //将生成的验证码保存到Redis中，设置有效时间
            stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY +phone,code,LOGIN_CODE_TTL, TimeUnit.MINUTES);//有效期2mins
            return Result.ok();
    }

    @Override
    /**
     * 验证码登录
     */
    public Result login(LoginFormDTO loginForm,HttpSession session) {
        String phone=loginForm.getPhone();
        String code=loginForm.getCode();
        //校验手机号
        if(RegexUtils.isPhoneInvalid(phone)) {
            //不符合则返回错误信息
            return Result.fail("手机号格式错误");
        }
        //校验验证码
        //从redis获取验证码
        String codeInRedis=stringRedisTemplate.opsForValue().get(phone);

        //if(inputCode!= null &&codeInRedis.equals(inputCode)) {
        //方便测试，不进行验证码 校验
        if(code== null) {
            return Result.fail("验证码为空");
        }
            //判断是否为新用户，是则自动注册
            User user= query().eq("phone",phone).one();
            if(user==null){
                //如果表中无该用户，则注册一个
                user=new User();
                user.setPhone(phone);
                //随机昵称
                user.setNickName(USER_NICK_NAME_PREFIX+RandomUtil.randomString(10));
                //保存该新用户
                save(user);
            }
            //6.保存用户到Redis
            //(1)生成token
            String token = UUID.randomUUID().toString(true); //hutools包中的
            //(2)User转为HashMap存储
            UserDTO userDTO = BeanUtil.copyProperties(user,UserDTO.class);
            HashMap<Object, Object> userMap = new HashMap<>();
            userMap.put("id", userDTO.getId().toString());
            userMap.put("nickName", userDTO.getNickName());
            userMap.put("icon", userDTO.getIcon());

            //(3)存储到Redis
            String tokenKey = LOGIN_USER_KEY + token;
            stringRedisTemplate.opsForHash().putAll(tokenKey,userMap);

            //(4) 设置key失效期，这样使每次使用都会刷新失效时间，而在设置key的时候设置失效时间则无法达到这种效果
            stringRedisTemplate.expire(tokenKey,LOGIN_USER_TTL,TimeUnit.SECONDS);  //30分钟
        return Result.ok(token);
    }

}
